using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;
using Random = UnityEngine.Random;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance = null;

    public StartPanel startPanel;
    public MoneyPanel moneyPanel;
    public SelectEquipPanel selectEquipPanel;
    public SelectMissionPanel selectMissionPanel;
    public LoadingPanel loadingPanel;
    public WinPanel winPanel;
    public TipPanel tipPanel;

    public int WaterGunIndex { get; set; }
    public PanelState panelState = PanelState.MainMenu;

    void Start()
    {
        if (Instance == null)
        {
            Instance = this;
        }

        DontDestroyOnLoad(this);

        InitPlayerData();
        InitEquipData();
        InitMissionData();
        InitAudio();

        startPanel.Init();
        moneyPanel.Init();
        selectEquipPanel.Init();
        selectMissionPanel.Init();
        loadingPanel.Init();
        winPanel.Init();
        tipPanel.Init();
        SetPanelState(PanelState.MainMenu);
    }

    public void SetPanelState(PanelState panelState)
    {
        AdManager.ShowNative();
        AdManager.ShowBanner();

        this.panelState = panelState;
        startPanel.SetPanelActive(panelState == PanelState.MainMenu);
        selectEquipPanel.SetPanelActive(panelState == PanelState.Store);
        selectMissionPanel.SetPanelActive(panelState == PanelState.LevelSelections);
        moneyPanel.SetPanelActive(panelState != PanelState.Mission);
        winPanel.SetPanelActive(panelState == PanelState.Win);
        moneyPanel.SetMenuTitle(panelState);

        if (panelState == PanelState.Mission)
        {
            StopBGAudio();
        }
        else
        {
            GameManager.Instance.StopFootAudio();
        }
    }

    #region PlayerData

    private void InitPlayerData()
    {
        Coin = PrefsManager.GetInt(PrefsType.Coin_0.ToString());
    }

    public int Coin { get; set; }

    public void AddCoin(int num)
    {
        Coin += num;
        moneyPanel.RefreshMoney();
        PrefsManager.SetInt(PrefsType.Coin_0.ToString(), Coin);
    }

    public void CostCoin(int num)
    {
        if (Coin < num) return;
        else Coin -= num;

        moneyPanel.RefreshMoney();
        PrefsManager.SetInt(PrefsType.Coin_0.ToString(), Coin);
    }

    #endregion

    #region EquipData

    public List<EquipData> _equipDatas = new List<EquipData>();

    private void InitEquipData()
    {
        int index = 0;
        string key = $"{PrefsType.EquipData}11{index}";
        PrefsManager.SetBool(key, true);
        _equipDatas.Add(new EquipData(0, PrefsManager.GetBool(key), 2000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 3000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 4000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 5000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 5000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 5000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 5000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 5000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 5000));
        key = $"{PrefsType.EquipData}{++index}";
        _equipDatas.Add(new EquipData(1, PrefsManager.GetBool(key), 10000));
    }

    public void BuyEquip(int index, Action action = null)
    {
        //超出索引
        if (_equipDatas.Count - 1 < index) return;
        //已解锁
        if (_equipDatas[index].IsUnlock) return;
        //钱不够
        if (_equipDatas[index].EquipCost > Coin)
        {
            TipPanel.Instance.ShowPanel("金钱不足", "你需要更多的金钱来购买这个水枪。", () => { }, button1Str: "确认");
            return;
        }

        //购买成功
        CostCoin(_equipDatas[index].EquipCost);
        _equipDatas[index].IsUnlock = true;

        //本地储存购买记录
        string key = $"{PrefsType.EquipData}{index}";
        PrefsManager.SetBool(key, true);

        action?.Invoke();
    }

    #endregion

    #region Mission

    public List<MissionData> _missionDatas = new List<MissionData>();

    private int _missionIndex;
    private int _curMissionIndex;

    public int MissionIndex
    {
        get
        {
            _missionIndex = Mathf.Clamp(_missionIndex, 0, _missionDatas.Count - 1);
            return _missionIndex;
        }
        set { _missionIndex = value; }
    }

    public int MissionTime { get; set; }

    private void InitMissionData()
    {
        List<string> allKey = new List<string>();
        int index = 0;
        string key = $"{PrefsType.Mission}{index}";
        PrefsManager.SetBool(key, true);
        _missionDatas.Add(new MissionData(PrefsManager.GetBool(key), "垃圾箱", 2));

        key = $"{PrefsType.Mission}{++index}";
        _missionDatas.Add(new MissionData(PrefsManager.GetBool(key), "阿金的船", 3));
        allKey.Add(key);

        key = $"{PrefsType.Mission}{++index}";
        _missionDatas.Add(new MissionData(PrefsManager.GetBool(key), "泡泡摊", 2));
        allKey.Add(key);

        key = $"{PrefsType.Mission}{++index}";
        _missionDatas.Add(new MissionData(PrefsManager.GetBool(key), "菠萝屋", 4));
        allKey.Add(key);

        key = $"{PrefsType.Mission}{++index}";
        _missionDatas.Add(new MissionData(PrefsManager.GetBool(key), "海星屋", 3));
        allKey.Add(key);

        key = $"{PrefsType.Mission}{++index}";
        _missionDatas.Add(new MissionData(PrefsManager.GetBool(key), "蟹堡王", 3));
        allKey.Add(key);

        key = $"{PrefsType.Mission}{++index}";
        _missionDatas.Add(new MissionData(PrefsManager.GetBool(key), "海之霸", 5));
        allKey.Add(key);

        key = $"{PrefsType.Mission}{++index}";
        _missionDatas.Add(new MissionData(PrefsManager.GetBool(key), "章鱼屋", 5));
        allKey.Add(key);

        // SetAllMission(allKey, true);
    }

    public GameObject GetMissionPrefab(int index)
    {
        index = Mathf.Clamp(index, 0, Constants.PathMissions.Count - 1);
        return LoadPrefab(Constants.PathMissions[index], true);
    }

    public void UnlockMission(int index)
    {
        index = Mathf.Clamp(index, 0, _missionDatas.Count - 1);
        _missionDatas[index].IsUnlock = true;
        //本地储存解锁记录
        string key = $"{PrefsType.Mission}{index}";
        PrefsManager.SetBool(key, true);
    }

    public void NextMission()
    {
        MissionIndex += 1;
        UnlockMission(MissionIndex);
        loadingPanel.LoadSceneAsync(Constants.MainScene);
    }

    private void SetAllMission(List<string> keys, bool isLock)
    {
        for (int i = 0; i < keys.Count; i++)
        {
            PrefsManager.SetBool(keys[i], isLock);
        }
    }

    public int GetCurMissonIndex()
    {
        int index = -1;
        for (int i = 0; i < _missionDatas.Count; i++)
        {
            if (i == _missionDatas.Count - 1 && _missionDatas[_missionDatas.Count - 1].IsUnlock)
            {
                index = -1;
                break;
            }

            if (_missionDatas[i].IsUnlock && !_missionDatas[i + 1].IsUnlock)
            {
                index = i;
                break;
            }
        }

        return index;
    }

    #endregion

    #region Reward

    /// <summary>任务完成奖励</summary>
    public int GetRewardMissionEarn() => Constants.MissonRewrd[MissionIndex];

    /// <summary>质量</summary>
    public int GetRewardQuality() => Random.Range(Constants.MissonTimeReward[MissionIndex] - 20,
        Constants.MissonRewrd[MissionIndex] + 20);

    /// <summary>准确性</summary>
    public int GetRewardAccuracy() => Random.Range(Constants.MissonTimeReward[MissionIndex] - 20,
        Constants.MissonRewrd[MissionIndex] + 20);

    /// <summary>时间奖励</summary>
    public int GetRewardTime()
    {
        int needTime = Constants.MissonNeedTime[MissionIndex];
        return needTime / (MissionTime <= needTime ? needTime : MissionTime) * Constants.MissonTimeReward[MissionIndex];
    }

    #endregion

    #region Resources

    private Dictionary<string, GameObject> goDic = new Dictionary<string, GameObject>();

    public GameObject LoadPrefab(string path, bool cache = false)
    {
        GameObject prefab = null;
        if (!goDic.TryGetValue(path, out prefab))
        {
            prefab = Resources.Load<GameObject>(path);
            if (cache)
            {
                goDic.Add(path, prefab);
            }
        }

        GameObject go = null;
        if (prefab != null)
        {
            go = Instantiate(prefab);
        }

        return go;
    }

    private Dictionary<string, Sprite> spDic = new Dictionary<string, Sprite>();

    public Sprite LoadSprite(string path, bool cache = false)
    {
        Sprite sp = null;
        if (!spDic.TryGetValue(path, out sp))
        {
            sp = Resources.Load<Sprite>(path);
            if (cache)
            {
                spDic.Add(path, sp);
            }
        }

        return sp;
    }

    #region Audio

    [SerializeField] private AudioSource audioSource;
    [SerializeField] private AudioSource bgAudio;
    [SerializeField] private AudioSource uiAudio;
    [SerializeField] private AudioSource footAudio;
    [SerializeField] private AudioSource winAudio;

    private void InitAudio()
    {
        AudioClip bgAudioClip = AudioManager.GetInstance().LoadAudio(Constants.PathAudio_MainBgm, true);
        bgAudio.clip = bgAudioClip;
        AudioClip footAudioClip = AudioManager.GetInstance().LoadAudio(Constants.PathAudio_Footsteps, true);
        footAudio.clip = footAudioClip;
        AudioClip winAudioClip = AudioManager.GetInstance().LoadAudio(Constants.PathAudio_Win, true);
        winAudio.clip = winAudioClip;
    }

    public void PlayAudio(string path, bool isLoop = false)
    {
        AudioClip audio = AudioManager.GetInstance().LoadAudio(path, true);
        audioSource.clip = audio;
        audioSource.loop = isLoop;
        audioSource.Play();
    }

    public void PlayBGAudio() => bgAudio.Play();

    public void StopBGAudio() => bgAudio.Stop();

    public void PlayFootAudio() => footAudio.Play();

    public void StopFootAudio() => footAudio.Stop();

    public void PlayWinAudio() => winAudio.Play();

    public void PlayUIAudio(string path, bool isLoop = false)
    {
        AudioClip audio = AudioManager.GetInstance().LoadAudio(path, true);
        uiAudio.clip = audio;
        uiAudio.loop = isLoop;
        uiAudio.Play();
    }

    public void PlayBtnClickAudio() => PlayUIAudio(Constants.PathAudio_BtnClick);

    public void StopAudio() => audioSource.Stop();

    #endregion

    #endregion

    #region System

    public void LoadScene(string sceneName)
    {
        switch (sceneName)
        {
            case Constants.StartScene:
                SetPanelState(PanelState.MainMenu);
                break;
            case Constants.MainScene:
                SetPanelState(PanelState.Mission);
                loadingPanel.LoadSceneAsync(Constants.MainScene);
                break;
            default:
                SetPanelState(PanelState.MainMenu);
                break;
        }
    }

    public void Quit() => Application.Quit();

    #endregion
}